package com.jillchen.grpc.server.utils;

import ch.qos.logback.core.util.FileUtil;
import com.aspose.imaging.ImageOptionsBase;
import com.aspose.imaging.fileformats.psd.ColorModes;
import com.aspose.imaging.fileformats.psd.CompressionMethod;
import com.aspose.imaging.imageoptions.*;
import com.aspose.note.FileFormat;
import com.aspose.pdf.*;
import com.aspose.pdf.devices.EmfDevice;
import com.aspose.pdf.devices.Resolution;
import com.aspose.slides.exceptions.Exception;
import com.aspose.words.FileFormatInfo;
import com.aspose.words.FileFormatUtil;
import org.apache.commons.imaging.ImageInfo;
import org.apache.commons.io.FilenameUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

public abstract class AbsConverter {


    /**
     * 转换文件
     *
     * @param InFile  输入文件
     * @param OutFile 出处文件
     * @return
     */
    public int Convert(String InFile, String OutFile) {
        return -1;
    }

    /**
     * 转换流对象
     *
     * @param inputStream  输入文件流
     * @param InFile       输入文件名
     * @param outputStream 转换后的文件流
     * @param OutFile      转换后的文件名
     * @return
     */
    public int Convert(InputStream inputStream, String InFile, ByteArrayOutputStream outputStream, String OutFile) {
        return -1;
    }

    /**
     * 添加水印
     *
     * @param InputPdf      输入文件
     * @param WaterMarkFile 水印文件
     * @param WaterMarkText 水印文字
     * @param OutFile       输出文件
     * @return 是否成功
     * @throws java.lang.Exception
     */
    public int WaterMark(String InputPdf, String WaterMarkFile, String WaterMarkText, String OutFile) throws java.lang.Exception {

        if (WaterMarkFile.equals("") && WaterMarkText.equals("")) {
            System.out.println("水印文件/或文字不存在");
            return -1;
        }
        //FileFormatInfo ffi= FileFormatUtil.detectFileFormat(InputPdf);
        File in_file = new File(InputPdf);
        File w_file = new File(WaterMarkFile);
        if (!in_file.exists()) {
            System.out.println("原始文件不存在");
            return -1;
        }
        if (!w_file.exists() && WaterMarkText.equals("")) {
            System.out.println("必须传入水印文件或水印文字");
            return -1;
        }

        String FileExt = FilenameUtils.getExtension(InputPdf).toUpperCase();
        //Aspose.Words 添加水印的文件后缀
        List<String> DocsExts = Arrays.asList(
                "wps",
                "wpt",
                "doc",
                "dot",
                "docx",
                "docm",
                "dotx",
                "dotm",
                "odt",
                "ott"
        );

        List<String> ImagingExts = Arrays.asList(
                "bmp",
                "tiff",
                "jpeg",
                "jpg",
                "png",
                "tif",
                "gif",
                "webp",
                "svg"
        );

        //Aspose.Pdf 添加水印
        List<String> PdfExts = Arrays.asList(
                "pdf"
        );
        try {
            String InputFileExt = FilenameUtils.getExtension(InputPdf).toLowerCase();
            if (DocsExts.contains(InputFileExt)) {

                com.aspose.words.Document doc = new com.aspose.words.Document(InputPdf);
                if (!WaterMarkText.equals("")) {
                    WordWaterMark.insertWatermarkText(doc, WaterMarkText);
                    doc.save(OutFile);
                } else {
                    return -1;
                }
            } else if (PdfExts.contains(InputFileExt)) {


                Document pdfDocument = new Document(InputPdf);
                //添加水印
                PageCollection pages = pdfDocument.getPages();
                //pdf 或图片水印
                if (w_file.exists()) {
                    String WFileExt = FilenameUtils.getExtension(WaterMarkFile).toUpperCase();
                    if (WFileExt.equals("PDF")) {
                        PdfPageStamp pdfStamp = new PdfPageStamp(WaterMarkFile, 1);
                        pdfStamp.setOpacity(0.1);
                        for (Page p : pages) {
                            p.addStamp(pdfStamp);
                        }
                    } else {
                        try {
                            ImageInfo II = org.apache.commons.imaging.Imaging.getImageInfo(w_file);
                            //org.apache.commons.imaging
                            // create image stamp
                            ImageStamp imageStamp = new ImageStamp(WaterMarkFile);
                            imageStamp.setXIndent(100);
                            imageStamp.setYIndent(100);
                            imageStamp.setHeight(II.getHeight());
                            imageStamp.setWidth(II.getWidth());
                            imageStamp.setOpacity(0.4);
                            for (Page p : pages) {
                                p.addStamp(imageStamp);
                            }
                        } catch (Exception ex) {
                            System.out.println("图片格式错误");
                            return -2;
                        }
                    }

                } else {
                    //文字水印
                    TextStamp textStamp = new TextStamp(WaterMarkFile);
                    // set origin
                    textStamp.setXIndent(100);
                    textStamp.setYIndent(100);
                    // rotate stamp
                    textStamp.setRotate(Rotation.on90);
                    // set text properties
                    textStamp.getTextState().setFont(new FontRepository().findFont("Arial"));
                    textStamp.getTextState().setFontSize(14.0F);
                    textStamp.getTextState().setFontStyle(FontStyles.Bold);
                    textStamp.getTextState().setFontStyle(FontStyles.Italic);
                    textStamp.getTextState().setForegroundColor(Color.getGreen());
                    textStamp.setOpacity(4.0E-01);

                    TextStamp textStamp1 = new TextStamp(WaterMarkFile);
                    // set properties of the stamp
                    textStamp1.setTopMargin(10);
                    textStamp1.setHorizontalAlignment(HorizontalAlignment.Center);
                    textStamp1.setVerticalAlignment(VerticalAlignment.Top);
                    // set text properties
                    textStamp1.getTextState().setFont(new FontRepository().findFont("Arial"));
                    textStamp1.getTextState().setFontSize(14.0F);
                    textStamp1.getTextState().setFontStyle(FontStyles.Bold);
                    textStamp1.getTextState().setFontStyle(FontStyles.Italic);
                    textStamp1.getTextState().setForegroundColor(Color.getGreen());
                    textStamp1.setOpacity(4.0E-01);
                    for (Page p : pages) {
                        p.addStamp(textStamp);
                        p.addStamp(textStamp1);
                    }
                }
                pdfDocument.save(OutFile, SaveFormat.Pdf);
            } else if (ImagingExts.contains(InputFileExt)) {
                try (com.aspose.imaging.Image image = com.aspose.imaging.Image.load(InputPdf)) {
                    ImagingWaterMark.AddWatermark(image, WaterMarkText);
                }

            } else {
                System.out.println("该格式不支持水印:" + InputFileExt);
                return -2;
            }
        } catch (Exception ex) {
            System.out.println("添加水印失败");
            return -2;
        }
        return 0;

    }


    /**
     * 文件流添加水印
     *
     * @param inputStream       欲添加水印的文件流
     * @param InputFileName     输入文件流名称
     * @param WaterMarkStream   水印文件流
     * @param WaterMarkFileName 输入文件流名称
     * @param WaterMarkText     水印文字
     * @param outputStream      添加完成的水印流
     * @param OutFileName       添加完水印的文件名
     * @return
     */
    public int WaterMark(InputStream inputStream
            , String InputFileName
            , InputStream WaterMarkStream
            , String WaterMarkFileName
            , String WaterMarkText
            , ByteArrayOutputStream outputStream, String OutFileName) throws java.lang.Exception {
        //判断流对象是否为空
        try {
            inputStream = new NonEmptyInputStream(inputStream);
        } catch (IOException e) {
            System.out.println("水印文件/或文字不存在");
            return -1;
        }

        boolean w_file=!"".equals(WaterMarkFileName);


        String FileExt = FilenameUtils.getExtension(InputFileName).toUpperCase();
        //Aspose.Words 添加水印的文件后缀
        List<String> DocsExts = Arrays.asList(
                "wps",
                "wpt",
                "doc",
                "dot",
                "docx",
                "docm",
                "dotx",
                "dotm",
                "odt",
                "ott",
                "html"
        );

        List<String> ImagingExts = Arrays.asList(
                "bmp",
                "tiff",
                "jpeg",
                "jpg",
                "png",
                "tif",
                "gif",
                "webp",
                "svg"
        );

        //Aspose.Pdf 添加水印
        List<String> PdfExts = Arrays.asList(
                "pdf"
        );

        String InputFileExt = FileExt.toLowerCase();
        String OutFileExt = FilenameUtils.getExtension(OutFileName).toLowerCase();
        String WFileExt = FilenameUtils.getExtension(WaterMarkFileName).toUpperCase();

        if (DocsExts.contains(InputFileExt))
        {
            com.aspose.words.Document doc = new com.aspose.words.Document(inputStream);
            if (!WaterMarkText.equals("")) {
                WordWaterMark.insertWatermarkText(doc, WaterMarkText);
                if ("html".equals(OutFileExt)) {
                    com.aspose.words.HtmlSaveOptions options = new com.aspose.words.HtmlSaveOptions();
                    options.setExportFontsAsBase64(true);
                    options.setExportImagesAsBase64(true);
                    options.setSaveFormat(com.aspose.words.SaveFormat.fromName(FileExt));
                    doc.save(outputStream, options);
                } else {
                    doc.save(outputStream, com.aspose.words.SaveFormat.fromName(OutFileExt));
                }
            }
        }
        else  if (PdfExts.contains(InputFileExt))
        {


            Document pdfDocument = new Document(inputStream);
            //添加水印
            PageCollection pages = pdfDocument.getPages();
            //pdf 或图片水印
            if (w_file) {
                if (WFileExt.equals("PDF")) {
                    PdfPageStamp pdfStamp = new PdfPageStamp(WaterMarkStream, 1);
                    pdfStamp.setOpacity(0.5);
                    for (Page p : pages) {
                        p.addStamp(pdfStamp);
                    }
                } else {
                    try {
                        ImageInfo II = org.apache.commons.imaging.Imaging.getImageInfo(WaterMarkStream,WaterMarkFileName);
                        //org.apache.commons.imaging
                        // create image stamp
                        ImageStamp imageStamp = new ImageStamp(WaterMarkStream);
                        imageStamp.setXIndent(100);
                        imageStamp.setYIndent(100);
                        imageStamp.setHeight(II.getHeight());
                        imageStamp.setWidth(II.getWidth());
                        imageStamp.setOpacity(0.4);
                        for (Page p : pages) {
                            p.addStamp(imageStamp);
                        }
                    } catch (Exception ex) {
                        System.out.println("图片格式错误");
                        return -2;
                    }
                }

            } else {
                //文字水印
                TextStamp textStamp = new TextStamp(WaterMarkText);
                // set origin
                textStamp.setXIndent(100);
                textStamp.setYIndent(100);
                // rotate stamp
                textStamp.setRotate(Rotation.on90);
                // set text properties
                textStamp.getTextState().setFont(new FontRepository().findFont("Arial"));
                textStamp.getTextState().setFontSize(14.0F);
                textStamp.getTextState().setFontStyle(FontStyles.Bold);
                textStamp.getTextState().setFontStyle(FontStyles.Italic);
                textStamp.getTextState().setForegroundColor(Color.getGreen());
                textStamp.setOpacity(4.0E-01);

                TextStamp textStamp1 = new TextStamp(WaterMarkText);
                // set properties of the stamp
                textStamp1.setTopMargin(10);
                textStamp1.setHorizontalAlignment(HorizontalAlignment.Center);
                textStamp1.setVerticalAlignment(VerticalAlignment.Top);
                // set text properties
                textStamp1.getTextState().setFont(new FontRepository().findFont("Arial"));
                textStamp1.getTextState().setFontSize(14.0F);
                textStamp1.getTextState().setFontStyle(FontStyles.Bold);
                textStamp1.getTextState().setFontStyle(FontStyles.Italic);
                textStamp1.getTextState().setForegroundColor(Color.getGreen());
                textStamp1.setOpacity(4.0E-01);
                for (Page p : pages) {
                    p.addStamp(textStamp);
                    p.addStamp(textStamp1);
                }
            }
            if ("XLS".equals(OutFileExt) || "XLSX".equals(OutFileExt)) {

                // Instantiate ExcelSave Option object
                ExcelSaveOptions excelsave = new ExcelSaveOptions();
                // Save the output to XLS format
                pdfDocument.save(outputStream, excelsave);
            } else if ("DOC".equals(OutFileExt)) {
                // Save the file into Microsoft document format
                pdfDocument.save(outputStream, SaveFormat.Doc);

            } else if ("DOCX".equals(OutFileExt)) {
                // Instantiate Doc SaveOptions instance
                DocSaveOptions saveOptions = new DocSaveOptions();
                // Set output file format as DOCX
                saveOptions.setFormat(DocSaveOptions.DocFormat.DocX);
                // Save resultant DOCX file
                pdfDocument.save(outputStream, saveOptions);
            } else if ("HTML".equals(OutFileExt)) {
                // Instantiate HTML Save options object
                HtmlSaveOptions newOptions = new HtmlSaveOptions();

                // Enable option to embed all resources inside the HTML
                newOptions.PartsEmbeddingMode = HtmlSaveOptions.PartsEmbeddingModes.EmbedAllIntoHtml;
                // This is just optimization for IE and can be omitted
                newOptions.LettersPositioningMethod = LettersPositioningMethods.UseEmUnitsAndCompensationOfRoundingErrorsInCss;
                newOptions.RasterImagesSavingMode = HtmlSaveOptions.RasterImagesSavingModes.AsEmbeddedPartsOfPngPageBackground;
                newOptions.FontSavingMode = HtmlSaveOptions.FontSavingModes.SaveInAllFormats;
                // Output file path

                // Save the output file
                pdfDocument.save(outputStream, newOptions);
            } else if ("EPUB".equals(OutFileExt)) {
                // Instantiate EPUB Save options
                EpubSaveOptions options = new EpubSaveOptions();
                // Specify the layout for contents
                options.ContentRecognitionMode = EpubSaveOptions.RecognitionMode.Flow;
                // Save the EPUB document
                pdfDocument.save(outputStream, options);
            }else if("SVG".equals(OutFileExt))
            {
                // instantiate an object of SvgSaveOptions
                SvgSaveOptions saveOptions = new SvgSaveOptions();
                // do not compress SVG image to Zip archive
                saveOptions.CompressOutputToZipArchive = false;
                pdfDocument.save(outputStream, saveOptions);

            }
            else if("PPTX".equals(OutFileExt))
            {
                PptxSaveOptions pptx_save = new PptxSaveOptions();
                pdfDocument.save(outputStream, pptx_save);
            }else{
                pdfDocument.save(outputStream, SaveFormat.Pdf);
            }
        }
        else if (ImagingExts.contains(InputFileExt))
        {
            try (com.aspose.imaging.Image image = com.aspose.imaging.Image.load(inputStream)) {
                ImagingWaterMark.AddWatermark(image, WaterMarkText);
                if (OutFileExt.equals("PDF")) {
                    com.aspose.imaging.imageoptions.PdfOptions psdOptions = new com.aspose.imaging.imageoptions.PdfOptions();
                    // Save image to disk in PSD format
                    image.save(outputStream, psdOptions);
                } else if (OutFileExt.equals("PSD")) {
                    PsdOptions psdOptions = new PsdOptions();
                    psdOptions.setColorMode(ColorModes.Rgb);
                    psdOptions.setCompressionMethod(CompressionMethod.RLE);
                    psdOptions.setVersion(4);
                    image.save(outputStream, psdOptions);
                } else if (OutFileExt.equals("WEBP")) {
                    // option
                    ImageOptionsBase options = new WebPOptions();
                    image.save(outputStream, options);
                } else {

                    ImageOptionsBase options = new PngOptions();
                    switch (OutFileExt) {
                        case "TIF":
                            options = new TiffOptions(0);
                            break;
                        case "JPEG":
                            options = new Jpeg2000Options();
                            break;
                        case "JPG":
                            options = new JpegOptions();
                            break;
                        case "PNG":
                            options = new PngOptions();
                            break;
                        case "TIFF":
                            options = new TiffOptions(0);
                            break;
                        case "GIF":
                            options = new GifOptions();
                            break;
                        case "SVG":
                            options = new SvgOptions();
                            break;
                        case "BMP":
                            options = new BmpOptions();
                            break;
                        default:
                            options = new PngOptions();
                            break;
                    }
                    // Initialize ImageSaveOptions

                    image.save(outputStream, options);
                }
            }

        }
        else
         {
            System.out.println("该格式不支持水印:" + InputFileExt);
            return -2;
        }
        return 0;
    }


}
